﻿using System;
using System.Collections.Generic;
using System.Linq;

namespace Wolfpack.Contrib.Checks.Powershell
{
    /// <summary>
    /// 
    /// </summary>
    public class RunspaceConfigurationCacheKey
    {
        /// <summary>
        /// The <see cref="StringComparer"/> to use when comparing snapin names and computing 
        /// hash values.
        /// </summary>
        private static readonly StringComparer _snapInNameComparer = StringComparer.InvariantCultureIgnoreCase;
        private readonly IEnumerable<string> _snapInNames;

        /// <summary>
        /// Initializes a new instance of the <see cref="RunspaceConfigurationCacheKey"/> class.
        /// </summary>
        /// <param name="snapInNames">The snap ins.</param>
        public RunspaceConfigurationCacheKey(IEnumerable<string> snapInNames)
        {
            // TODO: do not allow duplicate snapin names
            _snapInNames = snapInNames ?? Enumerable.Empty<string>();
        }

        /// <summary>
        /// Gets the PowerShell SnapIn list.
        /// </summary>
        public IEnumerable<string> SnapInNames
        {
            get { return _snapInNames; }
        }

        /// <summary>
        /// Returns a hash code for this instance.
        /// </summary>
        /// <returns>
        /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. 
        /// </returns>
        public override int GetHashCode()
        {
            return _snapInNames.Aggregate(0, (current, snapInName) => current ^ GetHashCode(snapInName));
        }

        /// <summary>
        /// Determines whether the specified <see cref="System.Object"/> is equal to this instance.
        /// </summary>
        /// <param name="obj">The <see cref="System.Object"/> to compare with this instance.</param>
        /// <returns>
        ///   <c>true</c> if the specified <see cref="System.Object"/> is equal to this instance; otherwise, <c>false</c>.
        /// </returns>
        public override bool Equals(object obj)
        {
            RunspaceConfigurationCacheKey key = obj as RunspaceConfigurationCacheKey;
            if (key == null)
            {
                return false;
            }

            HashSet<string> set = new HashSet<string>(this._snapInNames, _snapInNameComparer);
            bool equals = set.SetEquals(key._snapInNames);

            return equals;
        }

        /// <summary>
        /// Gets the hash code for the specified string.
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        private static int GetHashCode(string name)
        {
            return _snapInNameComparer.GetHashCode(name);
        }
    }
}